//
//$Id: app.cpp 687 2011-03-13 12:21:29Z andrew.tsyganov $
#include "stdafx.h"
#include "include/app.h"

#include "include/islsp_config.h"
#include "include/islsp_solution.h"
#include "include/islsp_sa.h"
#include "include/islsp_ga.h"
#include "include/islsp_gn.h"

#include "solvers/sa/sa_omp.h"
#include "solvers/ga/ga_omp.h"
#include "solvers/hybrids/weak_hybrid.h"

#include "src/heo/include/run_omp.h"

using namespace std;
using namespace app;

inline string ToLower(std::string const& s)
{
    string str = s;
    transform(str.begin(), str.end(), str.begin(), tolower);
    return str;
}

int App::run(int argc, char* argv[]) const
{
    string method = ToLower(argv[3]);

    if (method == "sa")    return sa(argc - 1, argv);
    if (method == "ga")    return ga(argc - 1, argv);
    if (method == "sa_gn") return sa_gn(argc - 1, argv);
    if (method == "ga_gn") return sa_gn(argc - 1, argv);
    
    cout << "Unknown method!" << endl;
    return -1;
}

int App::sa(int argc, char* argv[]) const
{
	typedef Islsp_Problem         TProblem;
	typedef Islsp_Solution        TSolution;
	typedef Islsp_Config          TConfig;

	typedef Environment<TProblem, TSolution, TConfig, Islsp_History>   TEnvironment;

	typedef struct SA_Traits<TEnvironment>              TTraits;
	typedef SA_OMP<TTraits>                             TSolver;

	return Run_OMP<TSolver>(argc, argv);
}

int App::ga(int argc, char* argv[]) const
{
	typedef Islsp_Problem         TProblem;
	typedef Islsp_Solution        TSolution;
	typedef Islsp_Config          TConfig;
	typedef Islsp_History         THistory;

	typedef Environment<TProblem, TSolution, TConfig, THistory> TEnvironment;

	typedef struct GA_Traits<TEnvironment>              TTraits;
	typedef GA_OMP<TTraits>                             TSolver;

	static struct ga_register
	{
		ga_register()
		{
			TSolver::register_Selection< ga::selection::tournament_selection >();
			TSolver::register_Selection< ga::selection::roulette_selection >();
			TSolver::register_Selection< ga::selection::random_selection >();

			TSolver::register_Operator< ga::inter_operator::crossover>();
			TSolver::register_Operator< ga::inter_operator::mutation>();
		}
	} reg;

	return Run_OMP<TSolver>(argc, argv);
}

int App::sa_gn(int argc, char* argv[]) const
{
	typedef Islsp_Problem         TProblem;
	typedef Islsp_Solution        TSolution;
	typedef Islsp_Config          TConfig;
	typedef Islsp_History         THistory; 

	typedef Environment<TProblem, TSolution, TConfig, THistory>      TEnvironment;

	typedef struct user_traits<TEnvironment> TGNTraits;
	typedef GN<TGNTraits>                    TSolverGN;

	typedef struct SA_Traits<TEnvironment> TTraitsSA;
	typedef SA_OMP<TTraitsSA>               TSolverSA;

	return Run_OMP< weak_hybrid<TSolverSA, TSolverGN, check_point_omp> >(argc, argv);
}

int App::ga_gn(int argc, char* argv[]) const
{
	typedef Islsp_Problem         TProblem;
	typedef Islsp_Solution        TSolution;
	typedef Islsp_Config          TConfig;
	typedef Islsp_History         THistory; 

	typedef Environment<TProblem, TSolution, TConfig, THistory>      TEnvironment;

	typedef struct user_traits<TEnvironment> TGNTraits;
	typedef GN<TGNTraits>                    TSolverGN;


	typedef struct GA_Traits<TEnvironment> TTraits1;
	typedef GA_OMP<TTraits1>               TSolverGA;

	static struct ga_register
	{
		ga_register()
		{
			TSolverGA::register_Selection< ga::selection::tournament_selection >();
			TSolverGA::register_Selection< ga::selection::roulette_selection >();
			TSolverGA::register_Selection< ga::selection::random_selection >();

			TSolverGA::register_Operator< ga::inter_operator::crossover>();
			TSolverGA::register_Operator< ga::inter_operator::mutation>();
		}
	} reg;

	return Run_OMP< weak_hybrid<TSolverGA, TSolverGN, check_point_omp> >(argc, argv);
}

void If_Debug_Press_Enter();

int main(int argc, char* argv[])
{
    App app;

    if (argc < 4)
    {
        cout << "Not enough parameters!" << endl;
		cout << "islsp_omp.exe seed config.xml method" << endl;
        If_Debug_Press_Enter();
        return 1;
    }
    else
    {
        int r = app.run(argc, argv);
        If_Debug_Press_Enter();
        return r;
    }
} 

//EOF!

